6525

33 分钟

#fenv.h

这个头文件提供 浮点数环境 的相关功能,例如浮点异常处理、舍入方向控制等。

需要链接数学库,例如在 gcc 中需要添加 -lm 链接选项。

浮点环境功能依赖于硬件和编译器的具体实现,可能需要手动开启:

  • 通过 #pragma STDC FENV_ACCESS ON 预处理指令可以开启浮点环境功能。

  • 通过 #pragma STDC FENV_ACCESS OFF 预处理指令可以关闭浮点环境功能。

  • 部分硬件或编译器可能不支持。

示例:

#include <stdio.h> #include <fenv.h> #include <math.h> #include <errno.h> void show_exceptions(void) { printf("当前浮点异常状态: "); if (fetestexcept(FE_ALL_EXCEPT) == 0) { printf("无异常\n"); return; } if (fetestexcept(FE_DIVBYZERO)) printf("除零异常 "); if (fetestexcept(FE_INVALID)) printf("无效操作异常 "); if (fetestexcept(FE_OVERFLOW)) printf("上溢异常 "); if (fetestexcept(FE_UNDERFLOW)) printf("下溢异常 "); if (fetestexcept(FE_INEXACT)) printf("不精确结果异常 "); printf("\n"); } void show_rounding_mode(void) { printf("当前舍入模式: "); switch (fegetround()) { case FE_TONEAREST: printf("四舍五入\n"); break; case FE_DOWNWARD: printf("向负无穷方向舍入\n"); break; case FE_UPWARD: printf("向正无穷方向舍入\n"); break; case FE_TOWARDZERO: printf("向零舍入\n"); break; default: printf("未知模式\n"); } } int main() { // 1. 显示初始浮点环境 printf("=== 初始浮点环境 ===\n"); show_exceptions(); show_rounding_mode(); printf("\n"); // 2. 触发浮点异常示例 printf("=== 触发浮点异常 ===\n"); feclearexcept(FE_ALL_EXCEPT); // 清除所有异常标志 // 除零异常 double x = 1.0, y = 0.0; double z = x / y; printf("1.0 / 0.0 = %f\n", z); show_exceptions(); // 无效操作异常 double a = sqrt(-1.0); printf("sqrt(-1.0) = %f\n", a); show_exceptions(); printf("\n"); // 3. 舍入模式控制示例 printf("=== 舍入模式控制 ===\n"); fesetround(FE_DOWNWARD); // 设置为向负无穷舍入 show_rounding_mode(); double num = 1.75; printf("1.75 舍入后: %f\n", rint(num)); fesetround(FE_UPWARD); // 设置为向正无穷舍入 show_rounding_mode(); printf("1.75 舍入后: %f\n", rint(num)); fesetround(FE_TONEAREST); // 恢复默认舍入模式 printf("\n"); // 4. 浮点环境保存与恢复 printf("=== 环境保存与恢复 ===\n"); fenv_t env; fegetenv(&env); // 保存当前环境 // 修改环境 fesetround(FE_TOWARDZERO); feclearexcept(FE_ALL_EXCEPT); printf("修改后的环境:\n"); show_rounding_mode(); show_exceptions(); fesetenv(&env); // 恢复原始环境 printf("\n恢复后的环境:\n"); show_rounding_mode(); show_exceptions(); return 0; }

运行结果:

user@host:~ $ gcc main.c -lm
user@host:~ $ ./a.out
=== 初始浮点环境 ===
当前浮点异常状态: 无异常
当前舍入模式: 四舍五入

=== 触发浮点异常 ===
1.0 / 0.0 = inf
当前浮点异常状态: 除零异常
sqrt(-1.0) = -nan
当前浮点异常状态: 除零异常 无效操作异常

=== 舍入模式控制 ===
当前舍入模式: 向负无穷方向舍入
1.75 舍入后: 1.000000
当前舍入模式: 向正无穷方向舍入
1.75 舍入后: 2.000000

=== 环境保存与恢复 ===
修改后的环境:
当前舍入模式: 向零舍入
当前浮点异常状态: 无异常

恢复后的环境:
当前舍入模式: 四舍五入
当前浮点异常状态: 除零异常 无效操作异常 不精确结果异常

#类型

类型标准说明
fenv_tC99表示整个浮点环境的类型
fexcept_tC99表示整个浮点异常标志的类型

#函数

函数标准说明
feclearexcepC99清除指定的浮点异常
fetestexceptC99检查指定的浮点异常
feraiseexceptC99产生指定的浮点异常
fegetexceptflagC99整体获取浮点异常标志
fesetexceptflagC99整体设置浮点异常标志
fegetroundC99获取舍入方向
fesetroundC99设置舍入方向
fegetenvC99获取浮点环境
fesetenvC99设置浮点环境
feholdexceptC99保存浮点环境并清空浮点异常
feupdateenvC99恢复浮点环境并触发浮点异常

#

标准说明
FE_DFL_ENVC99指向默认浮点环境的指针
浮点数异常宏标准说明
FE_ALL_EXCEPTC99所有支持的浮点异常的按位或
FE_DIVBYZEROC99浮点运算中发生了极点错误
FE_INEXACTC99结果不精确:需要进行舍入才能存储
FE_INVALIDC99浮点运算中发生了域错误
FE_OVERFLOWC99浮点运算的结果太大而溢出
FE_UNDERFLOWC99浮点运算的结果太小而损失精度
浮点数舍入方向宏标准说明
FE_DOWNWARDC99向负无穷方向舍入
FE_TONEARESTC99四舍五入到最接近的可表示值
FE_TOWARDZEROC99向零舍入
FE_UPWARDC99向正无穷方向舍入

创建于 2025/6/1

更新于 2025/6/5